package com.koi.generator.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.koi.common.anno.KoiLog;
import com.koi.common.enums.log.OperType;
import com.koi.common.ex.koi.YUtil;
import com.koi.common.satoken.KoiLoginUtil;
import com.koi.generator.pojo.GenCode;
import com.koi.generator.service.gencloumn.GenColumnService;
import com.koi.generator.service.gentable.GenTableService;
import com.koi.model.vo.gen.GenTableVo;
import com.koi.pojo.gen.GenColumn;
import com.koi.pojo.gen.GenTable;
import com.koi.pojo.gen.TableData;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * @author ･ᴗ･
 * @description [代码生成业务表-控制层]
 */
@Validated
@RequestMapping("/koi")
@RequiredArgsConstructor
@RestController
public class GenTableController {

    private final GenTableService genTableService;

    private final GenColumnService genColumnService;

    /**
     * @description [分页查询]
     * @author ･ᴗ･
     */
    @GetMapping("/genTable/listPage")
    public IPage<GenTable> listPage(GenTableVo vo) {
        // 分页构造器
        Page<GenTable> page = new Page<>(vo.getPageNo(), vo.getPageSize());
        // 条件构造器
        LambdaQueryWrapper<GenTable> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(vo.getTableName()), GenTable::getTableName, vo.getTableName());
        wrapper.like(StringUtils.isNotBlank(vo.getClassName()), GenTable::getClassName, vo.getClassName());
        wrapper.like(StringUtils.isNotBlank(vo.getTableComment()), GenTable::getTableComment, vo.getTableComment());
        // 进行分页查询
        page = genTableService.page(page, wrapper);
        return page;
    }

    /**
     * @description [查询所有]
     * @author ･ᴗ･
     */
    @GetMapping("/genTable/list")
    public List<GenTable> list() {
        return genTableService.list();
    }

    /**
     * @description [查询一个]
     * @author ･ᴗ･
     */
    @GetMapping("/genTable/getById/{id}")
    public GenTable getById(@PathVariable Long id) {
        return genTableService.getById(id);
    }

    /**
     * @description [新增]
     * @author ･ᴗ･
     */
    @PostMapping("/genTable/add")
    public void add(@Validated @RequestBody GenTable genTable) {
        genTable.setCreateBy(KoiLoginUtil.getUserName());
        YUtil.isTrue(!genTableService.save(genTable), "新增失败，请稍后重试");
    }

    /**
     * @description [修改]
     * @author ･ᴗ･
     */
    @PostMapping("/genTable/update")
    public void update(@Validated @RequestBody GenTable genTable) {
        if(genTable.getTableTemplate().equals("tree")) {
            YUtil.isTrue(StringUtils.isBlank(genTable.getTreeId()) || StringUtils.isBlank(genTable.getTreePid()) || StringUtils.isBlank(genTable.getTreeName()),"请选择树编码、树父编码、树编码名称");
        }
        YUtil.isTrue(!genTableService.updateById(genTable), "修改失败，请稍后重试");
    }

    /**
     * @description [删除]
     * @author ･ᴗ･
     */
    @KoiLog(title = "代码生成删除", operType = OperType.DELETE)
    @SaCheckPermission("system:role:delete")
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/genTable/deleteById/{id}")
    public void delete(@PathVariable("id") Long id) {
        LambdaQueryWrapper<GenTable> genTableWrapper = new LambdaQueryWrapper<>();
        genTableWrapper.eq(GenTable::getTableId, id);
        GenTable genTable = genTableService.getOne(genTableWrapper);
        if (ObjectUtils.isNotEmpty(genTable) && genTable.getTableName() != null) {
            genColumnService.remove(new LambdaQueryWrapper<GenColumn>().eq(GenColumn::getTableName, genTable.getTableName()));
        }
        YUtil.isTrue(!genTableService.removeById(id), "删除失败，请稍后重试");
    }

    /**
     * @description [批量删除]
     * @author ･ᴗ･
     */
    @KoiLog(title = "代码生成批量删除", operType = OperType.DELETE)
    @SaCheckPermission("system:role:delete")
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/genTable/batchDelete")
    public void batchDelete(@RequestBody List<Long> ids) {
        for (Long id : ids) {
            LambdaQueryWrapper<GenTable> genTableWrapper = new LambdaQueryWrapper<>();
            genTableWrapper.eq(GenTable::getTableId, id);
            GenTable genTable = genTableService.getOne(genTableWrapper);
            if (ObjectUtils.isNotEmpty(genTable) && genTable.getTableName() != null) {
                genColumnService.remove(new LambdaQueryWrapper<GenColumn>().eq(GenColumn::getTableName, genTable.getTableName()));
            }
        }
        YUtil.isTrue(!genTableService.removeBatchByIds(ids), "删除失败，请稍后重试");
    }

    /**
     * @description [根据表名查询一个]
     * @author ･ᴗ･
     */
    @GetMapping("/genTable/getByTableName/{tableSchema}/{tableName}")
    public GenTable getByTableName(@PathVariable("tableSchema") String tableSchema, @PathVariable("tableName") String tableName) {
        return genTableService.getOne(new LambdaQueryWrapper<GenTable>().eq(GenTable::getTableSchema, tableSchema).eq(GenTable::getTableName, tableName));
    }

    /**
     * @description [导入表格数据-获取当前数据库下的所有表名称及注释]
     * 为什么这里用 koi-model的TableData 而不是用 tableClass，因为koi-mybatis-plus 引用的类在 koi-model
     * @author ･ᴗ･
     */
    @GetMapping("/genTable/listAllTableName")
    public Map<String, Object> listAllTableName(TableData vo) {
        return genTableService.listAllTableName(vo);
    }

    /**
     * @description [导入数据]
     * @author ･ᴗ･
     */
    @PostMapping("/genTable/importGenTable")
    public void importGenTable(@RequestBody TableData vo) {
        genTableService.importGenTable(vo);
    }

    /**
     * @param tableName 数据库表名，例如：sys_login_user
     * @description [同步数据]
     * @author ･ᴗ･
     */
    @GetMapping("/genTable/synchronousData/{tableSchema}/{tableName}")
    public void synchronousData(@PathVariable("tableSchema") String tableSchema, @PathVariable("tableName") String tableName) {
        genTableService.synchronousData(tableSchema, tableName);
    }

    /**
     * @description [保存列数据]
     * @author ･ᴗ･
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/genTable/saveColumnData")
    public void saveColumnData(@RequestBody List<GenColumn> list){
        // 1、先删除列数据
        genColumnService.remove(new LambdaQueryWrapper<GenColumn>().eq(GenColumn::getTableName, list.get(0).getTableName()));
        // 2、保存新的列数据
        boolean batchSave = genColumnService.saveBatch(list);
        YUtil.isTrue(!batchSave, "保存失败");
    }

    /**
     * @param genCodeList 生成代码数据库名称 和 表名称
     * @param type 类型 [preview-预览代码 gen-生成代码]
     * @description [通过前端生成代码]
     * @author ･ᴗ･
     */
    @KoiLog(title = "预览代码", operType = OperType.GENCODE)
    @PostMapping("/genTable/previewPerfectCode/{type}")
    public Map<String, Object> previewPerfectCode(@NotNull(message = "请选择需要预览的数据") @Validated @RequestBody List<GenCode> genCodeList, @PathVariable("type") String type) {
        return genTableService.previewPerfectCode(genCodeList, type);
    }

    /**
     * @param genCodeList 生成代码数据库名称 和 表名称
     * @param type 类型 [preview-预览代码 gen-生成代码]
     * @description [通过前端生成代码]
     * @author ･ᴗ･
     */
    @KoiLog(title = "生成代码", operType = OperType.GENCODE)
    @PostMapping("/genTable/generatePerfectCode/{type}")
    public void generatePerfectCode(@NotNull(message = "请选择需要生成的数据") @Validated @RequestBody List<GenCode> genCodeList, @PathVariable("type") String type) {
        genTableService.generatePerfectCode(genCodeList, type);
    }

}
